use std::cell::{Ref, RefCell};
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::thread;
use crate::{bound, InBoundServer, JaegerTracing, SidecarConfig, TcpClient};
use crate::bound::outbound::OutBoundServer;
use crate::resource::resource::{Resource, ResourceString};

pub struct MeshClient
{
    config:SidecarConfig,
    tcp_client:RefCell<TcpClient>,
    resource:Arc<Mutex<HashMap<ResourceString,Vec<Resource>>>>,
    inbound_server:InBoundServer,
    outbound_server:OutBoundServer,
}

impl MeshClient {
    pub fn new(config: SidecarConfig) -> MeshClient {
        let mut tcp_client = TcpClient::new(bound::TcpClientPort as u32);
        let trace = JaegerTracing::new(config.service_ip.as_str(), config.service_name.as_str());
        let inbound = InBoundServer::new(config.container_port as i32, Some(trace));
        let outbound = OutBoundServer::new();
        let resource = Arc::new(Mutex::new(HashMap::new()));
        let borrow = resource.clone();

        let mut mc = MeshClient {
            config,
            tcp_client: RefCell::new(tcp_client),
            resource,
            inbound_server: inbound,
            outbound_server: outbound
        };

        mc.tcp_client.borrow_mut().add_fn("update".to_string(),move |data: Vec<u8>| -> Vec<u8> {
            let res: serde_json::Result<HashMap<String, Vec<Resource>>> = serde_json::from_slice(data.as_slice());
            match res {
                Err(e) => {
                    return Vec::new();
                }
                Ok(data) => {
                    let mut m: HashMap<ResourceString, Vec<Resource>> = HashMap::new();
                    for (k, v) in data {
                        m.insert(ResourceString::new(k), v);
                    }
                    *borrow.lock().unwrap() = m;

                    return "ok".to_string().into_bytes();
                }
            }
        });

        mc
    }

    pub fn run(self) {}
}